package com.woniuxy.project.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniuxy.commons.entity.Invest;
import com.woniuxy.commons.request.ResPage;
import com.woniuxy.commons.service.FeignReceivablesService;
import com.woniuxy.commons.service.FeignRepaymentService;
import com.woniuxy.commons.util.SnowflakeIdWorker;
import com.woniuxy.commons.vo.AddAddTimeToReceivablesVo;
import com.woniuxy.commons.vo.ProjectVo;
import com.woniuxy.commons.vo.SearchProjectVo;
import com.woniuxy.project.entity.IndexData;
import com.woniuxy.project.entity.Project;
import com.woniuxy.project.mapper.ProjectMapper;
import com.woniuxy.project.service.ProjectService;
import com.woniuxy.project.vo.AddProjectVo;
import com.woniuxy.project.vo.ReviewProjectVo;
import com.woniuxy.project.vo.SearchReceivablesVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ProjectServiceImpl implements ProjectService {

    @Resource
    private ProjectMapper projectMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private FeignReceivablesService receivablesService;

    @Resource
    private FeignRepaymentService repaymentService;

    @Override
    public ResPage<List<ProjectVo>> searchProject(SearchProjectVo searchProjectVo) {
        //  分页
        PageHelper.startPage(searchProjectVo.getPage(), searchProjectVo.getSize());
        List<ProjectVo> list = projectMapper.searchProject(searchProjectVo);
        log.info(list.toString());
        ResPage<List<ProjectVo>> resPage = getListResPage(list);
        return resPage;
    }

    @Transactional
    @Override
    public boolean addProject(AddProjectVo addProjectVo) {
        //  生成项目编号
        SnowflakeIdWorker worker = new SnowflakeIdWorker(1001);
        String no = worker.nextId() + "";
        //  将更新数据放入对象中
        addProjectVo.setPno(no);
        //  生成需要数据
        BigDecimal rate = addProjectVo.getRate().divide(new BigDecimal(100));
        addProjectVo.setRate(rate);
        if ((addProjectVo.getLoanrate() != null) ){
//            || (!addProjectVo.getLoanrate().equals(0))
            BigDecimal loanrate = addProjectVo.getLoanrate().divide(new BigDecimal(100));
            addProjectVo.setLoanrate(loanrate);
        }
        if ((addProjectVo.getBonusrate() != null) ){
//            || (!addProjectVo.getBonusrate().equals(0))
            BigDecimal bonusrate = addProjectVo.getBonusrate().divide(new BigDecimal(100));
            addProjectVo.setBonusrate(bonusrate);
        }
        //  将项目放入数据库
        projectMapper.addProject(addProjectVo);
        return true;
    }

    @Transactional
    @Override
    public boolean updateProject(AddProjectVo addProjectVo) {
        //  生成需要数据
        BigDecimal rate = addProjectVo.getRate().divide(new BigDecimal(100));
        addProjectVo.setRate(rate);
        if (addProjectVo.getLoanrate() != null || addProjectVo.getLoanrate().equals(0)){
            BigDecimal loanrate = addProjectVo.getLoanrate().divide(new BigDecimal(100));
            addProjectVo.setLoanrate(loanrate);
        }
        if (addProjectVo.getBonusrate() != null || addProjectVo.getBonusrate().equals(0)){
            BigDecimal bonusrate = addProjectVo.getBonusrate().divide(new BigDecimal(100));
            addProjectVo.setBonusrate(bonusrate);
        }
        //  将数据放入数据库中
        return projectMapper.updateProject(addProjectVo);
    }

    @Override
    public AddProjectVo checkDetail(String pno) {
        return projectMapper.checkDetail(pno);
    }

    @Transactional
    @Override
    public boolean passPreliminaryExamination(ProjectVo projectVo) {
        if (projectMapper.passPreliminaryExamination(projectVo.getPno())){
            //  将pno作为key放入redis中
            Date now = new Date();
            //  获取AddProjectVo对象，获得招标开始时间
            AddProjectVo addProjectVo = checkDetail(projectVo.getPno());
            //  判断开始时间与当前时间的差值,如果开始时间小于当前时间，抛异常
            if (now.getTime()/1000 > addProjectVo.getStarttime().toEpochSecond(ZoneOffset.UTC)){

            }
            //  如果大于一天，计算时间差（秒钟），然后通过当前秒杀id作为key放入redis，并且将时间差作为过期时间
            long startTime = addProjectVo.getStarttime().toEpochSecond(ZoneOffset.UTC) - now.getTime()/1000;
            String startKey = "project_start_" + addProjectVo.getPno();
            redisTemplate.opsForValue().set(startKey, null, startTime, TimeUnit.SECONDS);
            //  放入结束时间
            long endTime = startTime + addProjectVo.getCollecttime() * 24 * 60 * 60;
            String endKey = "project_end_" + addProjectVo.getPno();
            redisTemplate.opsForValue().set(endKey, null, endTime, TimeUnit.SECONDS);
            Long startExpireTime = redisTemplate.getExpire(startKey,TimeUnit.SECONDS);
            log.debug("开始时间过期还有：" + startExpireTime);
            Long endExpireTime = redisTemplate.getExpire(endKey,TimeUnit.SECONDS);
            log.debug("开始时间过期还有：" + endExpireTime);
        }
        return true;
    }

    @Override
    public void startInviteTenders(String pno) {
        projectMapper.startInviteTenders(pno);
    }

    @Override
    public void endInviteTenders(String pno) {
        //  根据pno查询金额
        Project project = projectMapper.searchCmoney(pno);
        if (!project.getStatus().equals("招标中")){
            return;
        }
        //  判断招标金额是否达标
        Integer comparisonResult = project.getMoney().compareTo(project.getCmoney());
        if (comparisonResult <= 0){
            projectMapper.endInviteTenders(pno);
        }else {
            //  未达标，则修改状态为未达标
            projectMapper.notMeetingStandards(pno);
            //
        }
    }

    @Override
    public ResPage<List<ProjectVo>> searchExamineProject(SearchProjectVo searchProjectVo) {
        //  分页
        PageHelper.startPage(searchProjectVo.getPage(), searchProjectVo.getSize());
        List<ProjectVo> list = projectMapper.searchExamineProject(searchProjectVo);
        ResPage<List<ProjectVo>> resPage = getListResPage(list);
        return resPage;
    }

    @Transactional
    @Override
    public Boolean withdrawProject(ProjectVo project) {
        if(!project.getCmoney().equals(0)){
            // 查投资详情表，将金额退还
            receivablesService.refund(project.getPno());
        }
        return projectMapper.withdrawProject(project);
    }

    @Override
    public List<SearchReceivablesVo> checkReceivables(String pno) {
        return projectMapper.checkReceivables(pno);
    }

    @Override
    public ResPage<List<ProjectVo>> searchFullProject(SearchProjectVo searchProjectVo) {
        //  分页
        PageHelper.startPage(searchProjectVo.getPage(), searchProjectVo.getSize());
        List<ProjectVo> list = projectMapper.searchFullProject(searchProjectVo);
        ResPage<List<ProjectVo>> resPage = getListResPage(list);
        return resPage;
    }

    @Override
    public boolean ReviewFailed(ProjectVo projectVo) {
        if(!projectVo.getCmoney().equals(0)){
            // 查投资详情表，将金额退还
            receivablesService.refund(projectVo.getPno());
        }
        return projectMapper.ReviewFailed(projectVo);
    }

    @Override
    public boolean passReexamine(ProjectVo projectVo) {
        //  修改项目数据单状态为复审通过
        if (projectMapper.passReexamine(projectVo.getPno())){
            //  将复审通过的消息合成key放入redis中
            Integer deadline = projectVo.getDeadline();
            Integer overdueKeyTime = deadline * 30 * 24 * 60 * 60;
            String overdueKey = "project_overdue_" + projectVo.getPno();
            redisTemplate.opsForValue().set(overdueKey, null, overdueKeyTime, TimeUnit.SECONDS);
        }else {
            return false;
        }
        //  添加t_receivables的预计回款时间
        Date now = new Date();
        getNewDate(now, projectVo.getDeadline() * 30);
        LocalDateTime estimatedRepaymentTime = LocalDateTime.ofInstant(
                getNewDate(now, projectVo.getDeadline() * 30).toInstant(),
                ZoneId.systemDefault()
        );
        AddAddTimeToReceivablesVo addAddTimeToReceivablesVo = new AddAddTimeToReceivablesVo(projectVo.getPno(), estimatedRepaymentTime);
        receivablesService.setAddTime(addAddTimeToReceivablesVo);
        //  添加t_repayment的数据记录
        repaymentService.addRepayment(projectVo);
        return true;
    }

    @Override
    public ResPage<List<ReviewProjectVo>> searchReviewProject(SearchProjectVo searchProjectVo) {
        //  分页
        PageHelper.startPage(searchProjectVo.getPage(), searchProjectVo.getSize());
        List<ReviewProjectVo> list = projectMapper.searchReviewProject(searchProjectVo);
        // 获取分页信息
        PageInfo<ReviewProjectVo> pageInfo = new PageInfo<>(list);
        ResPage<List<ReviewProjectVo>> resPage = new ResPage<>();
        resPage.setCurPage(pageInfo.getPageNum());
        resPage.setSize(pageInfo.getSize());
        resPage.setTotal(pageInfo.getTotal());
        resPage.setTotalPage(pageInfo.getPages());
        resPage.setData(pageInfo.getList());
        return resPage;
    }

    @Override
    public boolean bid(Invest invest) {
        return projectMapper.bid(invest);
    }

    public static Date getNewDate(Date startDate, int i) {
        // TODO Auto-generated method stub
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(startDate);
        calendar.add(Calendar.DATE, i); //把日期往后增加一天,整数  往后推,负数往前移动
        return calendar.getTime();
    }

    private ResPage<List<ProjectVo>> getListResPage(List<ProjectVo> list) {
        // 获取分页信息
        PageInfo<ProjectVo> pageInfo = new PageInfo<>(list);
        ResPage<List<ProjectVo>> resPage = new ResPage<>();
        resPage.setCurPage(pageInfo.getPageNum());
        resPage.setSize(pageInfo.getSize());
        resPage.setTotal(pageInfo.getTotal());
        resPage.setTotalPage(pageInfo.getPages());
        resPage.setData(pageInfo.getList());
        return resPage;
    }
    @Override
    public IndexData getIndexData() {
        //获取value1-value8
        IndexData indexData = new IndexData();
        indexData.setValue1(projectMapper.getCountByStatus(indexData.getStatus1()));
        indexData.setValue2(projectMapper.getCountByStatus(indexData.getStatus2a()) + projectMapper.getCountByStatus(indexData.getStatus2b()));
        indexData.setValue3(projectMapper.getCountByStatus(indexData.getStatus3()));
        indexData.setValue4(projectMapper.getCountByStatus(indexData.getStatus4()));
        indexData.setValue5(projectMapper.getTotalInvestMoney());
        indexData.setValue6(projectMapper.getConsumerCount());
        indexData.setValue7(projectMapper.getTodayConsumerCount());
        indexData.setValue8(projectMapper.getTodayAddProjectCount());
        indexData.setValue9(projectMapper.getDailyTotalRecharge());
        indexData.setValue10(projectMapper.getDailyTotalWithdraw());
        List<BigDecimal> value11 = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            value11.add(projectMapper.getDailyTotalRecharge().get(i).add(projectMapper.getDailyTotalWithdraw().get(i)));
        }
        indexData.setValue11(value11);
        indexData.setValue12(projectMapper.getMonthTotalRecharge().add(projectMapper.getMonthTotalWithdraw()));
        indexData.setValue13(projectMapper.getWeekTotalWithdraw().add(projectMapper.getWeekTotalRecharge()));
        return indexData;
    }
}
